/******************************************************************************
	@Author: Manh Cuong
    @CreatDate: 12/07/2012
	@Application: rtc.c 
*******************************************************************************/

/*****************************************************************************/
/* INCLUSIONS                                                                                                                            */
/*****************************************************************************/
#include "rtc.h"
#include <stdbool.h>
#include <time.h>

static uint8_t RTC_UpdateTimeFlag = 0;
/******************************************************************************
** Function name: Time_Adjust()
** Description: This function adjust caliberate time
** Parameter X : unsigned long Value - time interger
** Return value: None
** Remarks: global variables used, side effects
******************************************************************************/
void Time_Adjust(unsigned long Value)
{
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
  /* Change the current time */
  RTC_SetCounter(Value);
  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();
}
/******************************************************************************
** Function name: Sec_Diff()
** Description: This function calculate raw time
** Parameter X : 
** Return value: None
** Remarks: global variables used, side effects
******************************************************************************/
unsigned long Sec_Diff( uint32_t st_day, uint32_t st_month, uint32_t st_year,
						uint32_t fs_day, uint32_t fs_month, uint32_t fs_year,
						uint32_t fs_hour, uint32_t fs_min, uint32_t fs_sec )
{
  unsigned long _tmp=0,s_day=0,non_leap_year=0,leap_year = 0;
	unsigned long i;
	_tmp = fs_year-st_year;
	if(_tmp>0){
		_tmp -=2;
	  non_leap_year +=2;
		if(fs_year%4==0)
			leap_year = _tmp/4  ;
		else
			leap_year = _tmp/4 + 1;
	  non_leap_year += _tmp - leap_year ;
	}
	for(i=0;i<non_leap_year;i++)
		 s_day+=365;
	for(i=0;i<leap_year;i++)
		s_day+=366;
	for(i=1;i<fs_month;i++){
			switch(i){
				case 1:case 3:case 5:case 7:case 8:case 10:case 12:s_day+=31;break;
				case 4:case 6:case 9:case 11: s_day+=30;break;
				case 2: if(fs_year%4)s_day+=28;else s_day+=29;break;
				default: break;
			}
	}
	s_day+=fs_day - 1;
	return((s_day*24*3600) + (fs_hour*3600) + (fs_min*60) + fs_sec);
}
/*************************************************************************/
/**
  * @brief  Configures the RTC.
  		-Side Effect : access to BKP Domain
  * @param  None
  * @retval None
  */
/*************************************************************************/
static void RTC_Configuration(void)
{
  /* Enable PWR and BKP clocks */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

	/* Allow access to BKP Domain */
	PWR_BackupAccessCmd(ENABLE);

	/* Reset Backup Domain */
	//BKP_DeInit();

	/* Enable LSE */
	RCC_LSEConfig(RCC_LSE_ON);
	/* Wait till LSE is ready */
	while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
	{}

	/* Select LSE as RTC Clock Source */
	RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

	/* Enable RTC Clock */
	RCC_RTCCLKCmd(ENABLE);

	/* Wait for RTC registers synchronization */
	RTC_WaitForSynchro();

	/* Wait until last write operation on RTC registers has finished */
	RTC_WaitForLastTask();

	/* Enable the RTC Second */
	RTC_ITConfig(RTC_IT_SEC, ENABLE);

	/* Wait until last write operation on RTC registers has finished */
	RTC_WaitForLastTask();

	/* Set RTC prescaler: set RTC period to 1sec */
	RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

	/* Wait until last write operation on RTC registers has finished */
	RTC_WaitForLastTask();
}
/*****************************************************************************/
/* DEFINITION OF GLOBAL FUNCTIONS (APIs, Callbacks and MainFunction(s))      */
/*****************************************************************************/
/******************************************************************************
** Function name: RTC_GetTime
** Description: The function use get time in RTC module
** Parameter X :  DateTimeType* - poit to user time struct
** Return value: None
** Remarks: global variables used, side effects
******************************************************************************/
void RTC_GetTime
(
  DateTimeType* DateTime 
)
{
  /* time GMT struct */
  time_t s_sec = RTC_GetCounter();
	struct  tm  *now = localtime(&s_sec);
  DateTime->Hour = now -> tm_hour;
	DateTime->Min = now -> tm_min;
	DateTime->Sec = now -> tm_sec;
	DateTime->Day = now -> tm_mday;
	DateTime->Month = now -> tm_mon + 1;
	if(now->tm_year+1900>=2000)
	  DateTime->Year	= now->tm_year+1900 - 2000;
	else
	  DateTime->Year	= 0;
}
/******************************************************************************
** Function name: RTC_IRQHandler()
** Description: This function shall processing rtc interrupt request
** Parameter X : None
** Return value: None
** Remarks: global variables used, side effects
******************************************************************************/
void RTC_IRQHandler(void)
{
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
  {

    /* Clear the RTC Second interrupt */
    RTC_ClearITPendingBit(RTC_IT_SEC);
    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
    /* Update time */
    RTC_UpdateTimeFlag = 1;
  }
}
/******************************************************************************
** Function name: RTC_init()
** Description: This function shall be init  hardware rtc
** Parameter X : None
** Return value: None
** Remarks: global variables used, side effects
******************************************************************************/
void RTC_Init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;

  /* Configure one bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  /* Enable the RTC Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
   /* RTC Configuration */
  RTC_Configuration();
  /* set Now function */
}
/******************************************************************************
** Function name: RTC_GetFlag
** Description: The function return value of rtc flag
** Parameter X : None
** Return value: None
** Remarks: global variables used, side effects
******************************************************************************/
uint8_t RTC_GetFlag
(
   void
)
{
  return RTC_UpdateTimeFlag;
}
/******************************************************************************
** Function name: RTC_ClearFlag
** Description: The function clear internal update time flag
** Parameter X : None
** Return value: None
** Remarks: global variables used, side effects
******************************************************************************/
void RTC_ClearUpdateTimeFlag
(
   void
)
{
  RTC_UpdateTimeFlag = 0;
}

